"""
This module is for doing date and time related operations that are useful or specific for our project.
"""

import datetime

iso_8601 = '%Y-%m-%d %H:%M:%S'
"""
The ISO 8601 format for date and time strings that can be used for strf formatting. Assumed to be in local time zone without tz suffix.
"""
iso_8601_utc = '%Y-%m-%dT%H:%M:%SZ'
"""
The ISO 8601 format for date and time strings that can be used for strf formatting. Assumed to be in UTC because of the Zulu ('Z') tz suffix.
"""

def totimestamp(datetime):
	"""
	Takes in a datetime object and turns it into an iso timestamp without ms
	"""
	return '-'.join([str(datetime.year), str(datetime.month), str(datetime.day)]) + 'T' + ':'.join([str(datetime.hour), str(datetime.minute), str(datetime.second)])

def todatetime(timestamp):
	"""
	Takes in a timestamp string formatted in ISO 8601 and returns a datetime object for it.
	"""
	if timestamp.endswith('Z'):
		return datetime.datetime.strptime(timestamp.strip(), iso_8601_utc)
	else:
		return datetime.datetime.strptime(timestamp.strip(), iso_8601)

def year(timestamp):
	"""
	Takes in a timestamp string formatted in ISO 8601 and returns a string of its year, using datetime, which is slow but exact.
	"""
	return str(todatetime(timestamp).year)

def year_fast(timestamp):
	"""
	Takes in a timestamp string formatted in ISO 8601 and returns a string of its year, using string math, which is fast but not robust.
	"""
	return timestamp.split('T')[0].split('-')[0]

def duration(begin, end):
	"""
	Takes in beginning and end timestamps formatted in ISO 8601 and returns a datetime.timedelta object for their difference.
	"""
	return todatetime(end) - todatetime(begin)

def offsetyear(begin, end):
	"""
	Takes in beginning and end timestamps formatted in ISO 8601 and the offset in years between them as a string.
	Uses the datetime timedelta object for comparison, which is more exact (within reason) but slow.
	This is not exact, but good enough for our purposes.
	"""
	return str(int(duration(begin, end).days/365.2425))

def offsetyear_fast(begin, end):
	"""
	Takes in beginning and end timestamps formatted in ISO 8601 and the offset in years between them as an integer.
	Uses string based date math, which is less exact but very fast and uses very little memory.
	Also exact enough for our purposes.
	"""
	beginDate = begin.split('T')[0].split('-')
	endDate = end.split('T')[0].split('-')
	
	for i in range(len(beginDate)):
		beginDate[i] = int(beginDate[i])
		endDate[i] = int(endDate[i])

	offset = endDate[0] - beginDate[0]
	if endDate[1] < beginDate[1]:
		offset -= 1
	elif endDate[1] == beginDate[1]:
		if endDate[2] < beginDate[2]:
			offset -= 1
		elif endDate[2] == beginDate[2]:
			if end.strip(' Z').split('T')[1] < begin.strip(' Z').split('T')[1]:
				offset -= 1
	return offset
	

def now():
	"""
	Returns a timestamp for the current time in ISO 8601.
	"""
	return datetime.datetime.now().strftime(iso_8601)

def before_fast(begin, end):
	"""
	Will tell if a begin timestamp takes place before an end timestamp quickly. Can be formatted in ISO 8601 or just a simple date format
	"""

	begindate = begin.strip().split('T')[0].split('-')
	enddate = end.strip().split('T')[0].split('-')

	if enddate[0] > begindate[0]:
		return True;
	elif enddate[0] == begindate[0]:
		if enddate[1] > begindate[1]:
			return True
		elif enddate[1] == begindate[1]:
			if enddate[2] > begindate[2]:
				return True
			elif enddate[2] == begindate[2]:
				if len(begin.split('T')) > 1 and len(end.split('T')) > 1:
					begintime = begin.strip().split('T')[1].rstrip('Z').split(':')
					endtime = end.strip().split('T')[1].rstrip('Z').split(':')

					if endtime[0] > begintime[0]:
						return True
					elif endtime[0] == begintime[0]:
						if endtime[1] > begintime[1]:
							return True
						elif endtime[1] == begintime[1]:
							if endtime[2] > begintime[2]:
								return True	

	return False

def after_fast(begin, end):
	"""
	 Will tell if an end timestamp takes place ater a begin timestamp. Can be formated in ISO 8601 or just simple date format
	"""

	return begin.strip() != end.strip() and not before_fast(begin, end)

def same_date_fast(date1, date2):
	""" 
	Will tell you if two timestamps (ISO 8601 or simple date) are the same date, if they are the same instant they should be identical
	"""

	return date1.strip().split('T')[0] == date2.strip().split('T')[0]
